package control

import (
	"context"
	"fmt"
	"dockerui/models"
	ut "dockerui/utils"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/filters"
	"github.com/docker/docker/client"
	"github.com/fatih/structs"
	"time"
)

func dockerContainer(skip int, limit int, search string) ([]models.ContainerFormatResp, int, error) {
	var (
		cli *client.Client
		containerListopt *types.ContainerListOptions
		containers []types.Container
		containerMap map[string]interface{}
		containerQuit bool
		ctx context.Context
		cancel context.CancelFunc
		containerResp []map[string]interface{}
		err error
		verifiedSkip int
		verifiedLimit int
		containerFormatResp []models.ContainerFormatResp
	)
	ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	cli = ut.GClient
	// 查询所有容器
	if search == "" {
		containerListopt = &types.ContainerListOptions{
			All: true,
		}
	}else {
		/*
				参考源码
				目前源码有bug,没有对Quiet字段进行处理，所以无法查询退出的容器,源码里该字段已经废弃
			    提交的issue
			    https://github.com/moby/moby/issues/42092
				https://github.com/moby/moby/blob/master/integration-cli/docker_api_containers_test.go
		*/
		containerFilters := filters.NewArgs()
		if search == "exited" {
			containerFilters.Add("status", search)
		}else {
			containerFilters.Add("name", search)
		}
		// Limit 需要自己实现分页，不用源码里面的limit
		containerListopt = &types.ContainerListOptions{
			All: false,
			Quiet: containerQuit,
			//Limit: limit,
			Filters: containerFilters,
		}
	}
	if containers, err = cli.ContainerList(ctx, *containerListopt); err !=nil {
		fmt.Println("Get containers error")
		return nil, len(containerResp), err
	}else {
		for _, container := range containers {
			containerMap = structs.Map(&container)
			containerResp = append(containerResp, containerMap)
		}
	}
	containerFormatResp = ut.FormatContainerList(containerResp)
	verifiedSkip, verifiedLimit = ut.LimitVerify(skip, limit, len(containerResp))
	return containerFormatResp[verifiedSkip:verifiedLimit], len(containerResp), nil
}

func dockerContainerInspect(containerId string) (map[string]interface{}, int, error){
	/*
	    参考api源码
		https://github.com/moby/moby/blob/v20.10.7/client/interface.go#L48
	*/
	var (
		cli *client.Client
		ctx context.Context
		containerInspect types.ContainerJSON
		containerInspectResp map[string]interface{}
		err error
		cancel context.CancelFunc
	)

	ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	cli = ut.GClient

	if containerInspect, err = cli.ContainerInspect(ctx, containerId); err != nil {
		fmt.Println("container info error", err)
		return nil, 0, err
	}
	containerInspectResp = structs.Map(&containerInspect)
	return containerInspectResp, 1, nil
}